package com.denlaku.longan.config;

import com.denlaku.longan.core.BeanNames;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author tianx
 */
@Configuration
public class ThreadPoolConfig {
    @Bean
    @ConfigurationProperties(prefix = "thread-pool")
    public ThreadPoolProperties threadPoolProperties() {
        return new ThreadPoolProperties();
    }

    @Bean(name = BeanNames.IO_THREAD_POOL_EXECUTOR_NAME)
    public ThreadPoolExecutor threadPoolExecutor() {
        ThreadPoolProperties threadPoolProperties = threadPoolProperties();
        int corePoolSize = Math.max(threadPoolProperties.getCorePoolSize(), 0);
        int maximumPoolSize = Math.max(threadPoolProperties.getMaximumPoolSize(), Math.max(corePoolSize, 1));
        long keepAliveTime = Math.max(threadPoolProperties.getKeepAliveTime(), 0);
        int queueCapacity = Math.max(threadPoolProperties.getQueueCapacity(), 0);
        String namePrefix = threadPoolProperties.getNamePrefix();
        return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(queueCapacity), initThreadFactory(namePrefix));
    }

    private ThreadFactory initThreadFactory(String namePrefix) {
        final AtomicInteger integer = new AtomicInteger();
        return r -> {
            Thread thread = new Thread(r);
            thread.setDaemon(false);
            thread.setPriority(Thread.NORM_PRIORITY);
            thread.setName(namePrefix + "-" + integer.getAndIncrement());
            return thread;
        };
    }
}
